package org.hs.phd.odi.bgsub.tracking;

import java.util.Arrays;

import org.hs.phd.odi.bgsub.vob.VisualObject;
import org.hs.phd.odi.bgsub.vob.VisualObjectClass;
import org.hs.phd.odi.bgsub.vob.VisualObjectFeatures;

public class TrackedObject extends VisualObject{
	
	private static long trackNo = 0;

	private int unmatchingFrameCount;
	private long[] classificationCounts;
	private int matchingFramesCountInARow;

	private final int frameCountForCandidates;

	private final int maxUnmatchingFrameCount;

	public TrackedObject(VisualObject obj, int frameCountForCandidates, int maxUnmatchingFrameCount) {
		super(obj.getPolygon(), obj.getObjectClass());
		this.frameCountForCandidates = frameCountForCandidates;
		this.maxUnmatchingFrameCount = maxUnmatchingFrameCount;
		setFeatures(obj.getFeatures());
		setTrackNo(++trackNo);

		unmatchingFrameCount = 0;
		this.matchingFramesCountInARow = 0;
		classificationCounts = new long[ VisualObjectClass.values().length ];
		Arrays.fill(classificationCounts, 0);
		classificationCounts[obj.getObjectClass().ordinal()]++;
	}

	public void merge(TrackedObject otherObject) {
		for(int i = 1; i < classificationCounts.length; i++){
			classificationCounts[i] += otherObject.classificationCounts[i];
		}
		setObjectClassFromMaxClassificationCount();
		
		updateFeatures(otherObject.getFeatures());
		
		setTrackNo(Math.min(getTrackNo(), otherObject.getTrackNo()));

		
	}

	private void updateFeatures(VisualObjectFeatures features) {
		//TODO merge track features by using some averaging technique for SURF?
		setFeatures(features);
	}

	public void updateWithCurrentFrameMatch(VisualObject currentFrameVisualObject) {
		unmatchingFrameCount = 0;
		this.matchingFramesCountInARow++;
		classificationCounts[currentFrameVisualObject.getObjectClass().ordinal()]++;			
		setObjectClassFromMaxClassificationCount();
		polygon = currentFrameVisualObject.getPolygon();
		
		updateFeatures(currentFrameVisualObject.getFeatures());
	}

	private void setObjectClassFromMaxClassificationCount() {
		int currentMaxIndex = 0;
		long currentMax = classificationCounts[currentMaxIndex];

		for(int i = 1; i < classificationCounts.length; i++){
			if(classificationCounts[i] > currentMax ){
				currentMaxIndex = i;
				currentMax = classificationCounts[currentMaxIndex];
			}
		}
		
		setObjectClass(VisualObjectClass.values()[currentMaxIndex]);
	}

	public void incrementUnmatchingFrameCount() {
		matchingFramesCountInARow = 0;
		unmatchingFrameCount++;
	}

	public int getUnmatchingFrameCount() {
		return unmatchingFrameCount;
	}

	public int getMatchingFramesCountInARow() {
		return matchingFramesCountInARow;
	}

	public boolean isDroppable() {
		return unmatchingFrameCount > maxUnmatchingFrameCount;	
	}

	public boolean isStableTrack() {
		return matchingFramesCountInARow >= frameCountForCandidates;
	}

}